package
{
	import flash.geom.Point;
	
	import org.flixel.*;
	public class Train
	{
		protected var positions:Array = new Array();
		protected var player:Player;
		
		protected var animal1:TrainAnimal = null;
		protected var animal2:TrainAnimal = null;
		protected var animal3:TrainAnimal = null;
		protected var animal4:TrainAnimal = null;
		protected var animal5:TrainAnimal = null;
		protected var throwCount:int;
		protected var switchCount:int;
		protected var removeCount:int;
		protected var trainLength:int;
		protected var thrownSpeed:int;
		protected var walkingSpeed:int;
		
		[Embed(source="../music/throw.mp3")] protected var throwSound:Class;
		
		protected static const DISTANCE:int = 15;
		
		public function Train(thePlayer:Player)
		{
			player = thePlayer;
			trainLength = 0;
			throwCount = 30;
			switchCount = 20;
			thrownSpeed = 250;
			walkingSpeed = 160;
		}
		
		public function addAnimal(animal:TrainAnimal):void {
			if (animal1 == null) {
				animal1 = animal;
			} else if (animal2 == null) {
				animal2 = animal;
			} else if (animal3 == null) {
				animal3 = animal;
			} else if (animal4 == null) {
				animal4 = animal;
			} else {
				animal5 = animal;
			}
			trainLength++;
		}
		
		public function updateTrain():void {
			//compute the returning animals velocities.
			if (animal1 != null && animal1.returning) {
				computeReturn(animal1);
			}
			if (animal2 != null && animal2.returning) {
				computeReturn(animal2);
			}
			if (animal3 != null && animal3.returning) {
				computeReturn(animal3);
			}
			if (animal4 != null && animal4.returning) {
				computeReturn(animal4);
			}
			if (animal5 != null && animal5.returning) {
				computeReturn(animal5);
			}
			
			//updates the positions of the animals in the train to follow the path of the
			//player.
			if (player.velocity.x != 0 || player.velocity.y != 0) {
				positions.unshift(new Point(player.x, player.y));
			}
			if (animal1 != null && positions.length > 1*DISTANCE && !animal1.thrown) { 
				animal1.updatePostion(positions[1*DISTANCE]);
			}
			if (animal2 != null && positions.length > 2*DISTANCE && !animal2.thrown) { 
				animal2.updatePostion(positions[2*DISTANCE]);
			}
			if (animal3 != null && positions.length > 3*DISTANCE && !animal3.thrown) { 
				animal3.updatePostion(positions[3*DISTANCE]);
			}
			if (animal4 != null && positions.length > 4*DISTANCE && !animal4.thrown) { 
				animal4.updatePostion(positions[4*DISTANCE]);
			}
			if (animal5 != null && positions.length > 5*DISTANCE && !animal5.thrown) { 
				animal5.updatePostion(positions[5*DISTANCE]);
			}
			if (positions.length > (trainLength + 1)*DISTANCE) {
				positions.pop();
			}
			
			//rotating the train.
			if(FlxG.keys.X && switchCount == 20) {
				rotateTrain();
				switchCount--;
			}
			if (switchCount == 0) {
				switchCount = 20;
			} else if(switchCount != 20) {
				switchCount--;
			}
			
			//throwing the lead animal.
			if(FlxG.keys.SPACE && throwCount == 30) {
				if (Elemental.MODE == Elemental.FACEBOOK_MODE) {
					Elemental.achievements.updateChickenThrown();
				}
				throwAnimal();
				throwCount--;
			}
			if (throwCount == 0) {
				throwCount = 30;
			} else if(throwCount != 30) {
				throwCount--;
			}
		}
		
		/**
		 * Determines teh x and y velocity for the returning animal
		 * so it can get back to its position in the train.
		**/
		protected function computeReturn(animal:TrainAnimal):void {
			var temp1:Point;
			var temp2:Point;
			var angle:Number;
			temp1 = new Point(animal.x, animal.y);
			temp2 = new Point(player.x, player.y);
			if (Point.distance(temp1, temp2) < 5) {
				animal.returning = false;
				animal.thrown = false;
				animal.stopThrowingAnim();
			}
			angle = getAngle(temp1, temp2);
			animal.velocity.x = walkingSpeed * Math.cos(angle);
			animal.velocity.y = walkingSpeed * Math.sin(angle);
		}
		
		/**
		 * Train Rotation functionality.
		**/
		public function rotateTrain():void {
			var temp:TrainAnimal = animal1;
			if (animal2 == null) {
				animal1 = temp;
			} else {
				animal1 = animal2;
				if (animal3 == null) {
					animal2 = temp;
				} else {
					animal2 = animal3;
					if (animal4 == null) {
						animal3 = temp;
					} else {
						animal3 = animal4;
						if (animal5 == null) {
							animal4 = temp;
						} else {
							animal4 = animal5;
							animal5 = temp;
						}
					}
				}
			}
		}
		
		/**
		 * Determines which direction to throw the animal and the updated train. 
		**/
		public function throwAnimal():void {
			if(animal1 != null && !animal1.thrown) {
				if (!Music.MUTE) {
					FlxG.play(throwSound, 0.2);
				}
				animal1.thrown = true;
				animal1.startThrowingAnim();
				animal1.updatePostion(new Point(player.x, player.y));
				var num:int = player.theDirection();
				switch(num) {
					case 0: animal1.velocity.x = 0; animal1.velocity.y = -thrownSpeed; break;
					case 1: animal1.velocity.x = 0; animal1.velocity.y = thrownSpeed; break;
					case 2: animal1.velocity.x = -thrownSpeed; animal1.velocity.y = 0; break;
					case 3: animal1.velocity.x = thrownSpeed; animal1.velocity.y = 0; break;
					case 4: animal1.velocity.x = -thrownSpeed * Math.cos(3.14159/4); animal1.velocity.y = -thrownSpeed * Math.sin(3.14159/4); break;
					case 5: animal1.velocity.x = -thrownSpeed * Math.cos(3.14159/4); animal1.velocity.y = thrownSpeed * Math.sin(3.14159/4); break;
					case 6: animal1.velocity.x = thrownSpeed * Math.cos(3.14159/4); animal1.velocity.y = -thrownSpeed * Math.sin(3.14159/4); break;
					case 7: animal1.velocity.x = thrownSpeed * Math.cos(3.14159/4); animal1.velocity.y = thrownSpeed * Math.sin(3.14159/4); break;
					default: animal1.velocity.x = thrownSpeed; animal1.velocity.y = thrownSpeed; break;
				}
				rotateTrain();
			}
		}
		/**
		 * Removes an animal from the train. Useful for when they die
		 * killing monsters.
		**/
		public function remove():void {
			var max:int = 0;
			if (animal1 != null && animal1.dead) {
				animal1 = animal2;
				animal2 = animal3;
				animal3 = animal4;
				animal4 = animal5;
			}
			if (animal2 != null && animal2.dead) {
				animal2 = animal3;
				animal3 = animal4;
				animal4 = animal5;
			}
			if (animal3 != null && animal3.dead) {
				animal3 = animal4;
				animal4 = animal5;
			}
			if (animal4 != null && animal4.dead) {
				animal4 = animal5;
			}
			animal5 = null;
		}
		
		/**
		 * basic function for getting an angle between two points.
		**/
		protected function getAngle(start:Point, end:Point):Number {
			var angle:Number = Math.atan2((end.y - start.y) , (end.x - start.x));
			return angle;
		}
		
		public function removeAll():void {
			animal1 = null;
			animal2 = null;
			animal3 = null;
			animal4 = null;
			animal5 = null;
		}
	}
}